//
// Created by swe_dev on 25-3-16.
//

#ifndef AUTO_BOILER_HPP
#define AUTO_BOILER_HPP

#include "task.hpp"
#include "hx711_driver/hx711_driver.hpp"
#include "state_machine/fsm_autoboilersm.h"
#include "tim/pwm_generator.hpp"

#define BOILER_BASE_WEIGHT      80
#define BOILER_WATER_EMPTY      900

#define BOILER_NOTHING  800
#define BOILER_EMPTY    1000
#define BOILER_MIN_WATER 1500
#define BOILER_FULL     2350
#define BOILER_MAXIM    5000


class AutoBoiler : public Task {
public:
    AutoBoiler() {
        period_ms = 300U;
    }
    void init_task() override {
        auto_boiler_sm.state_register();
        auto_boiler_sm.start();
        hx711_driver = std::make_unique<Hx711Driver>(GPIOA, GPIO_PIN_4, GPIOA, GPIO_PIN_5);

        if (is_keydown(GPIOA, GPIO_PIN_1)) {
            task_yield(1000);
            if (is_keydown(GPIOA, GPIO_PIN_1)) {
                printf("calibration...\r\n");
                offset = hx711_driver->get_offset(3);
            }
        }
    }

    void period_task() override {
        int32_t weight = hx711_driver->get_weight(offset);
        printf("%d\r\n", weight);
        if (is_keydown(GPIOA, GPIO_PIN_1) &&
            weight > BOILER_NOTHING &&
            weight < BOILER_FULL) {
            auto_boiler_sm.dispatch(auto_boiler_sm.t_watering);
        }

        if (weight < BOILER_NOTHING) {
            auto_boiler_sm.dispatch(auto_boiler_sm.t_standby);
        }

        if (weight > BOILER_MIN_WATER) {
            auto_boiler_sm.dispatch(auto_boiler_sm.t_boiling);
        }

        if (weight > BOILER_FULL && weight < BOILER_MAXIM) {
            auto_boiler_sm.dispatch(auto_boiler_sm.t_full);
        }

    }

protected:
    static bool is_keydown(GPIO_TypeDef* gpio_bank, uint16_t pin, uint32_t down_state=0) {
        auto value = HAL_GPIO_ReadPin(gpio_bank, pin);
        if (value == down_state) {
            return true;
        }
        return false;
    }

protected:
//    int32_t offset{158794};
    int32_t offset{147752};
    AutoBoilerSM auto_boiler_sm{};
    std::unique_ptr<Hx711Driver> hx711_driver{nullptr};
};



#endif //AUTO_BOILER_HPP
